package cheme.ProcessEditor;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.swt.events.KeyEvent;


/*
 * This adds a specialization to the GraphicalViewerKeyHandler ability to navigate
 * on key presses, it delegates processes to installed IProcessKey instances.
 * For isntance, on a arrow key, navigation may occur. Pressing enter may invoke 
 * a certain type of request/command execution on the selected editpart.
 */
public class ChemeGraphicalKeyHandler extends GraphicalViewerKeyHandler
{
	List<IProcessKey> keyProcesses = new ArrayList<IProcessKey>();

	private static final int ENTER_KEY = 13;
	private static final int UNICODE_ENTER_KEY = 16777296;
	private static final int SPACE_KEY = ' ';
	
	public ChemeGraphicalKeyHandler(GraphicalViewer viewer)
	{
		super(viewer);
		
		/*
		 * Note that the base class KeyHandler can associate IAction instance 
		 * with a KeyStroke, something like this:
		 * put(KeyStroke.getPressed(16777217, 0), 
		 * 		new LeafFigureNavigator(getViewer(), 
		 * 								getFocusEditPart(), 
		 * 								PositionConstants.NORTH));
		 * 
		 * but it seems a little constrained with regard to navigating. The fact 
		 * that there is a different implementation of navigation in GEF itself
		 * attests to that. This is probably because KeyHandler is Eclipse specific
		 * and not aware of GEF needs.
		 * 
		 * Anyway, my approach is the same kinda of think, associating actions
		 * with a key stroke.
		 */
		
		/*
		 * handles leaf node level navigation
		 */
		keyProcesses.add(new KeyNavigator());
		
		/*
		 * Handles the issuance of the direct edit request to target editparts.
		 */
		keyProcesses.add(new AbstractKeyProcess()
		{
			public boolean handleKey(KeyEvent event, GraphicalEditPart focusPart)
			{
				super.handleKey(event, focusPart);
				
				if(SPACE_KEY == event.keyCode)
				{
					if(null != focusPart)
					{
						focusPart.performRequest(new Request(RequestConstants.REQ_OPEN));
					}
					
					return true;
				}
				
				return false; //let other GEF native processes handle the keypress too
			}
		});
		
//		keyProcesses.add(new AbstractKeyProcess()
//		{			
//			public boolean handleKey(KeyEvent event, GraphicalEditPart focusPart)
//			{
//				setFocusPart(focusPart);
//				
//				if(ENTER_KEY == event.keyCode || UNICODE_ENTER_KEY == event.keyCode)
//				{
//					if(null != focusPart)
//					{
//						Command cmd = focusPart.getCommand(new CreateAfterRequest(focusPart));
//						executeCommand(cmd);
//					}
//				}
//				return false; //let other GEF native processes handle the keypress too
//			}
//		});
	}
	
	/**
	 * Extended to process key events described above.
	 * @see org.eclipse.gef.KeyHandler#keyPressed(org.eclipse.swt.events.KeyEvent)
	 */
	@Override
	public boolean keyPressed(KeyEvent event)
	{
		boolean handled = false;
		
		for(IProcessKey process : keyProcesses)
		{
			handled |= process.handleKey(event, getFocusEditPart());
		}
		
		/*
		 * return handled if it is true, or give the super class teh option to handle.
		 */
		return (handled || super.keyPressed(event));
	}
}
